package com.excel.validators.core.decorative;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.excel.validators.core.extension.TypeConverter;
import com.excel.validators.log.Log;
import com.excel.validators.log.LogFactory;

/**
 * @author wangxiaoliang10
 *
 * 2017年8月7日
 */
@SuppressWarnings("rawtypes")
public class BasicClass {

	protected static final Log logger = LogFactory.getLog(BasicClass.class);
	
	public static final int BYTE = 0X0001;
	
	public static final int CHAR = 0X0002;
	
	public static final int SHORT = 0X0003;
	
	public static final int INTEGER = 0X0004;
	
	public static final int LONG = 0x0005;
	
	public static final int DOUBLE = 0x0006;
	
	public static final int FLOAT = 0x0007;
	
	public static final int BOOLEAN = 0x0008;
	
	public static final int BIGDECIMAL = 0x0009;
	
	public static final int DATE = 0x00a0;
	
	public static final int STRING = 0x00a1;
	
	public static final int UNNONE = 0x00000;
	
	private static Map<String,Class> clsMap;
	
	/**
	 * JDK6下模拟switch
	 * @param cls
	 * @return
	 */
	public static int enumType(String clsType) {
			
			Class cls = findClass(clsType);
			if (String.class == cls) {
					return STRING;
			} else if (int.class == cls || Integer.class == cls) {
					return INTEGER;
			} else if (long.class == cls || Long.class == cls) {
					return LONG;
			} else if (double.class == cls || Double.class == cls) {
					return DOUBLE;
			} else if (float.class == cls || Float.class == cls) {
					return FLOAT;
			} else if (boolean.class == cls || Boolean.class == cls) {
					return BOOLEAN;
			} else if (BigDecimal.class == cls) {
					return BIGDECIMAL;
			} else if (Date.class == cls) {
					return DATE;
			} else if (byte.class == cls || Byte.class == cls) {
					return BYTE;
			} else if (char.class == cls || Character.class == cls) {
					return CHAR;
			} else if (short.class == cls || Short.class == cls) {
					return SHORT;
			} else {
					logger.warn("The Type not supported: " + clsType);
					return UNNONE;
			}
	}	
	
	private static Class findClass(String clsType) {
			Class result = clsMap.get(clsType);
			if (result == null) {
					try {return Class.forName(clsType);} catch (ClassNotFoundException e) {}
			}
			return result;
	}

	private static Object convert(String value,FieldElement field) {
			try {
					switch (field.getBasicClass()) {
							case STRING :
									return TypeConverter.toString(value);
							case INTEGER :
									return TypeConverter.toInteger(value);
							case LONG :
									return TypeConverter.toLong(value);
							case DOUBLE :
									return TypeConverter.toDouble(value,field.getDecimal());
							case FLOAT :
									return TypeConverter.toFloat(value,field.getDecimal());
							case BOOLEAN :
									return TypeConverter.toBoolean(value);
							case BIGDECIMAL :
									return TypeConverter.toBigDecimal(value,field.getDecimal());
							case DATE :
									return TypeConverter.toDate(value,field.getPattern());
							case BYTE :
								return TypeConverter.toByte(value);
							case SHORT :
								return TypeConverter.toShort(value);
							case CHAR :
								return TypeConverter.toChar(value);
							default :
									return null;
							}
			} catch (Exception e) {
					return null;
			}
	}

	protected static FieldValue basic(String oleValue,FieldElement field) {
			Object newValue = convert(oleValue, field);
			return new FieldValue(field.getFieldName(),oleValue, newValue);
	}

	/*
	public static <V> V convert(String value,Class<V> cls) {
			// get model
			FieldElement model = findClass(cls);
			// TODO is collections
			Class<?> colsType = model.getColsType();
			//  convert
			try {
					if (colsType != null) {
							// add element
							Object[] basic = (Object[]) basic(value, model.getBasicType());
							if (basic != null) {
									// create collection object
									Collection<Object> cos = (Collection<Object>) colsType.newInstance();
									for (Object obj : basic) {
											cos.add(obj);
									}
									return (V) cos;
							}
					} else {
							return (V) basic(value, model.getBasicType());
					}
			} catch (Exception e) {
					if (logger.isDebugEnabled()) {
							logger.error("The value convert error: " + value + 
									" class type " + cls.getSimpleName(),e);
					}
			}
			return null;
	}
	*/

	/*
	public static FieldElement TypeOrientation(FieldElement model) {
			// get type
			Type clzss = model.getCls().getGenericSuperclass();
			Type type  = ((ParameterizedType) clzss).getActualTypeArguments()[0];
			try {
					if (type instanceof Class) {
							model.setBasicType(enumType((Class<?>)type));
					} else {
							Type colsType = ((ParameterizedType) type).getRawType();
							if (Collection.class.isAssignableFrom((Class<?>)colsType)) {
									model.setColsType(setColsType((Class<?>)colsType));
									Type base = ((ParameterizedType) type).getActualTypeArguments()[0];
									model.setBasicType(enumType((Class<?>)base) << 8);
							}
					}
			} catch (Exception e) {
					if (logger.isDebugEnabled()) {
							logger.error(e.getMessage());
					}
			}
			return null;
	}
	*/
	
	/**
	 * 容器类基本类型处理
	 * @param colsType
	 * @return

	public static Class<?> setColsType(Class<?> colsType) {
			if (List.class == colsType) {
					return ArrayList.class;
			} else if (ArrayList.class == colsType) {
					return ArrayList.class;
			} else if (LinkedList.class == colsType) {
					return LinkedList.class;
			} else if (Set.class == colsType) {
					return HashSet.class;
			} else if (HashSet.class == colsType) {
					return HashSet.class;
			} else if (LinkedHashSet.class == colsType) {
					return LinkedHashSet.class;
			} else if (TreeSet.class == colsType) {
					return TreeSet.class;
			}
			return null;
	}
	*/
	

	/**
	 *  tostring function
	 * @param audit
	 * @return

	public static String toString(AuditValue audit) {
			// get model
			FieldElement model = findClass(audit.getClass());
			int basicType = model.getBasicType();
			// TODO is Date type
			boolean isDate = basicType == DATE || basicType == LDATE;
			// TODO is collections
			Class<?> colsType = model.getColsType();
			
			if (colsType != null) {
					Collection cols = (Collection) audit.getValue();
					if (cols != null) {
							Object[] arrs = cols.toArray(new Object[cols.size()]);
							return TypeConverter.toArray(arrs, isDate);
					}
			} else if (basicType > DATE && basicType < UNNONE) {
					Object[] arrs = (Object[]) audit.getValue();
					if (arrs != null) {
							return TypeConverter.toArray(arrs, isDate);
					}
			} else if (basicType >= STRING && basicType <= DATE) {
					Object value = audit.getValue();
					if (value != null) {
							return TypeConverter.toArray(new Object[]{value}, isDate);
					}
			}
			return audit.getOldValue();
	}
	*/
	
	static {
			clsMap = new HashMap<String,Class>();
			clsMap.put("byte", byte.class);
			clsMap.put("char", char.class);
			clsMap.put("short", short.class);
			clsMap.put("int", int.class);
			clsMap.put("long", long.class);
			clsMap.put("float", float.class);
			clsMap.put("double", double.class);
			clsMap.put("boolean", boolean.class);
	}

	
}
